"""
Configuration / Settings for delineator.py

This file now supports environment variables through .env file.
You can either:
1. Create a .env file with your custom settings (recommended)
2. Edit the default values in this file directly

See README for more information about the options and for instructions
on how to download the input data for delineating watersheds in areas
outside of the sample data provided for Iceland.

"""

import os
from typing import Union

def str_to_bool(value: Union[str, bool]) -> bool:
    """Convert string to boolean, handling various string representations."""
    if isinstance(value, bool):
        return value
    if isinstance(value, str):
        return value.lower() in ('true', '1', 'yes', 'on')
    return bool(value)

def get_env_var(key: str, default_value: Union[str, bool, int, float]) -> Union[str, bool, int, float]:
    """Get environment variable with type conversion and default fallback."""
    env_value = os.getenv(key)
    if env_value is None:
        return default_value
    
    # Type conversion based on default value type
    if isinstance(default_value, bool):
        return str_to_bool(env_value)
    elif isinstance(default_value, int):
        try:
            return int(env_value)
        except ValueError:
            return default_value
    elif isinstance(default_value, float):
        try:
            return float(env_value)
        except ValueError:
            return default_value
    else:
        return env_value

# Try to load .env file if it exists - support multiple search paths
def load_env_files():
    """Load .env files from multiple possible locations."""
    try:
        from dotenv import load_dotenv
        
        # Possible .env file locations (in order of priority)
        env_paths = [
            # 1. Current working directory
            os.path.join(os.getcwd(), '.env'),
            # 2. User specified MGHYDRO_CONFIG_PATH
            os.getenv('MGHYDRO_CONFIG_PATH'),
            # 3. Package directory (for development)
            os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), '.env'),
            # 4. Home directory
            os.path.join(os.path.expanduser('~'), '.mghydro.env'),
        ]
        
        # Try to load from each path
        loaded = False
        for env_path in env_paths:
            if env_path and os.path.exists(env_path):
                load_dotenv(env_path)
                loaded = True
                if get_env_var('VERBOSE', True):
                    print(f"MGHydro: Loaded configuration from {env_path}")
                break
        
        if not loaded and get_env_var('VERBOSE', True):
            print("MGHydro: No .env file found, using default configuration")
            
    except ImportError:
        # dotenv not installed, continue with regular environment variables
        pass

# Load environment configuration
load_env_files()

def set_config_path(config_path: str):
    """
    Set custom configuration path and reload configuration.
    
    Args:
        config_path (str): Path to the .env file or directory containing .env file
    """
    if os.path.isdir(config_path):
        config_path = os.path.join(config_path, '.env')
    
    if os.path.exists(config_path):
        os.environ['MGHYDRO_CONFIG_PATH'] = config_path
        load_env_files()
        return True
    else:
        raise FileNotFoundError(f"Configuration file not found: {config_path}")

def reload_config():
    """Reload configuration from environment variables."""
    load_env_files()

# Path to your CSV file with the watershed outlet data
OUTLETS_CSV = get_env_var('OUTLETS_CSV', 'outlets_sample.csv')

# 主输出目录 - 所有输出都将放在此目录下
BASE_OUTPUT_DIR = get_env_var('BASE_OUTPUT_DIR', 'output')

# Set to True for "higher resolution" mode or False for "lower resolution."
HIGH_RES = get_env_var('HIGH_RES', True)

# Directory containing the merged, basin-scale MERIT-Hydro flow direction rasters (.tif)
# Download from https://mghydro.com/watersheds/rasters
# For all paths, do not include a trailing slash.
MERIT_FDIR_DIR = get_env_var('MERIT_FDIR_DIR', "data/raster/flowdir_basins")

# Directory containing the merged, basin-scale MERIT-Hydro flow accumulation rasters (.tif)
# Download from https://mghydro.com/watersheds/rasters
MERIT_ACCUM_DIR = get_env_var('MERIT_ACCUM_DIR', "data/raster/accum_basins")

# Set to True if you want the script to write status messages to the console
VERBOSE = get_env_var('VERBOSE', True)

# Set to True to make a bunch of plots of each watershed.
# (Just for debugging. Slows down the script a lot.)
PLOTS = get_env_var('PLOTS', True)

# Folder where you have stored the Merit-BASINS catchment shapefiles.
# These files need to be downloaded from: https://www.reachhydro.org/home/params/merit-basins
HIGHRES_CATCHMENTS_DIR = get_env_var('HIGHRES_CATCHMENTS_DIR', "data/shp/merit_catchments")

# Location of simplified unit catchment boundaries vector data (shapefiles)
# Download from: https://mghydro.org/watersheds/share/catchments_simplified.zip
LOWRES_CATCHMENTS_DIR = get_env_var('LOWRES_CATCHMENTS_DIR', "data/shp/catchments_simplified")

# Folder where you have stored the MERIT-Basins River flowline shapefiles
# Download from: https://www.reachhydro.org/home/params/merit-basins
RIVERS_DIR = get_env_var('RIVERS_DIR', "data/shp/merit_rivers")

# Folder where the script will write the output GeoJSON files or shapefiles
OUTPUT_DIR = get_env_var('OUTPUT_DIR', os.path.join(BASE_OUTPUT_DIR, "watersheds"))

# Output file extension. Supported formats: geojson (recommended), gpkg, shp, kml
# Use a blank string "" if you DO NOT want any geodata files (for example,
# you are only making the interactive map and don't need geodata).
# Other file formats are available;
# see: https://geopandas.org/en/stable/docs/user_guide/io.html#writing-spatial-data
# Note: For standardized output, geojson is now the default format
OUTPUT_EXT = get_env_var('OUTPUT_EXT', "geojson")

# Set to True to ouput a summary of the delineation in OUTPUT.CSV
OUTPUT_CSV = get_env_var('OUTPUT_CSV', True)

# Directory to store temporary data in memory cache. 
# The old PICKLE_DIR functionality has been replaced with in-memory LRU caching
# for better performance and to avoid disk-based temporary files.
# This setting is kept for backward compatibility but is no longer used.
PICKLE_DIR = get_env_var('PICKLE_DIR', "")

# Threshold for watershed size in km² above which the script will revert to
# low-resolution mode 
LOW_RES_THRESHOLD = get_env_var('LOW_RES_THRESHOLD', 50000)

# If the requested watershed outlet is not inside a catchment, how far away 
# from the point should we look for the nearest catchment (in degrees). 0.025 recommended
SEARCH_DIST = get_env_var('SEARCH_DIST', 0)

# Watersheds created with Merit-Hydro data tend to have many "donut holes"
# ranging from one or two pixels to much larger.
FILL = get_env_var('FILL', True)

# If FILL = True, you many choose to to fill donut holes that are below a
# certain size. This is the number of pixels, on the 3 arcsecond grid. 
# Set to 0 to fill ALL holes.
FILL_THRESHOLD = get_env_var('FILL_THRESHOLD', 100)

# Simplify the watershed boundary? This will remove some vertices 
# from the watershed boundary and output smaller files.
SIMPLIFY = get_env_var('SIMPLIFY', False)

# If SIMPLIFY is True, set SIMPLIFY_TOLERANCE to a value in decimal degrees.
SIMPLIFY_TOLERANCE = get_env_var('SIMPLIFY_TOLERANCE', 0.0008)

# Set to TRUE if you want the script to create a local web page where you 
# can review the results.
MAKE_MAP = get_env_var('MAKE_MAP', True)

# Folder where the script should put the map files. (MAKE sure it exists!)
# The mapping routine will make _viewer.html and .js files for every watershed
MAP_FOLDER = get_env_var('MAP_FOLDER', os.path.join(BASE_OUTPUT_DIR, "map"))

# Directory for plots output
PLOTS_DIR = get_env_var('PLOTS_DIR', os.path.join(BASE_OUTPUT_DIR, "plots"))

# 最终输出目录 - 如果设置，将把输出文件复制到此目录
# 留空表示不进行额外复制，只输出到本地 OUTPUT_DIR
# 设置为远程路径（如 /app/minio/shapefile/mghydro/）表示需要复制到该路径
FINAL_OUTPUT_DIR = get_env_var('FINAL_OUTPUT_DIR', "")

# On the map, do you also want to include the rivers?
MAP_RIVERS = get_env_var('MAP_RIVERS', True)

# On the web page map, if MAP_RIVERS is True, how many stream orders shall we display?
# I recommend 4 or less. More than this and the browser may not display all the rivers in a large watershed.
NUM_STREAM_ORDERS = get_env_var('NUM_STREAM_ORDERS', 3)

# Set to True to use the experimental match areas feature. 
# You must include the field `area` in your outlets CSV file to use this feature (in km²)
MATCH_AREAS = get_env_var('MATCH_AREAS', False)

# If you set MATCH_AREAS = True, how close of a match should the script look for?
# Enter 0.25 for 25%. If you set MATCH_AREAS to False you can ignore this parameter.
AREA_MATCHING_THRESHOLD = get_env_var('AREA_MATCHING_THRESHOLD', 0.25)

# If you set MATCH_AREAS = True, how far away from the original outlet point should the script look 
# for a river reach that is a better match in terms of upstream area?
# Units are decimal degrees (sorry, not a proper distance measurement, this feature could be improved!)
# 0.1° is about 11 km near the equator, and about 8 km near at a latitude of 45°
MAX_DIST = get_env_var('MAX_DIST', 0.075)

# Threshold for number of upstream pixels that defines a stream
# These values worked will in my testing, but you might try changing if the
# outlet is not getting snapped to a river centerline properly
THRESHOLD_SINGLE = get_env_var('THRESHOLD_SINGLE', 500)
THRESHOLD_MULTIPLE = get_env_var('THRESHOLD_MULTIPLE', 5000)
